//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __FAT32_H_
#define __FAT32_H_

typedef UInt32 fat32_t;

/* Contents of FAT32 filesystem information sector */
typedef struct fat32_info {
    UInt32 signature0;        /* Magic number 0 */
    UInt8 filler[0x1e0];
    UInt32 signature1;        /* Magic number 1 */
    UInt32 free;              /* Free clusters in filesystem */
    UInt32 last;              /* Last location allocated from */
} fat32_info;

class fat32
{
public:
    virtual int fat32_init(class fatfs_sharedata *pSharedata);
    virtual void fat32_sync(void);
    virtual struct clust * fat32_alloc(struct clust *c, struct directory *d);
    virtual int fat32_setlen(struct clust *c, UInt32 newclust);
    virtual int fat32_loadfat(class fatfs_sharedata *pSharedata);
    virtual void fat32_clearfatseg(void);
#if defined(_DEBUG)
    void fat32_stat(UInt32 *Fat_secs);
#endif
    virtual UInt64 fat32_calcfreespace();
    fat32();
    virtual ~fat32();

    class fatfs_sharedata *p_Sharedata;

private:
    fat32_t * lookup(UInt32 idx);
    fat32_t get(UInt32 idx);
    void set(UInt32 idx, fat32_t val);

    fat32_t **fatv;       /* Our in-core FAT sections */
    UInt32   fatlen,          /*  ...length of overall FAT */
            nfatv,         /*  ...number of slots in fatv array */
            fatvlen,      /*  ...byte size of fatv array */
            fatseg;        /*fatseg# allocate*/
    UInt8 *dirtymap;      /* Map of sectors with dirty FAT entries */
    UInt32   dirtymapsize;  /*  ...size of map */
    UInt32   nxt_clust;     /* Where last cluster search left off */
    UInt32   fatbase;         /* Sector # of base of FAT */
    UInt32   infobase, infosize;
    fat32_info *info;
};

/*-------------------------------------------------------------------------*/
/*FAT flag values for FAT-32                                               */
/*-------------------------------------------------------------------------*/
#define FAT32_RESERVED (0xFFFFFF0)      /* Start of reserved value range */
#define FAT32_DEFECT (0xFFFFFF7)        /* Cluster w. defective block */
#define FAT32_EOF (0xFFFFFF8)           /* Start of EOF range */
#define FAT32_END (0xFFFFFFF)           /* End of reserved range */

// Values for the signature[01] fields

#define INFOSECT_SIGNATURE0 0x41615252
#define INFOSECT_SIGNATURE1 0x61417272

/*
 * FATSEG()     Calculate segment index for fatv given cluster number
 */
#define FATSEGSIZE         (65536)  //(64*1024)
#define FATSEG(idx)        (((idx) * sizeof(fat32_t)) / FATSEGSIZE)
#define FATIDX(idx)        ((idx) % (FATSEGSIZE / sizeof(fat32_t)))
#define FATSEGMAX          16

/*
 * FATSECTSEG()  Convert sector index to segment index
 */
#define FATSECT(sect)      (((sect)<< p_Sharedata->secshift) / sizeof(fat32_t))
#define FATSECTSEG(sect)   FATSEG(FATSECT(sect))

#endif //__FAT32_H_
